/* hal_scu.h */
#ifndef __HAL_SCU_H__
#define __HAL_SCU_H__

#include "hal_common.h"

typedef enum
{
    SCU_ClkSrc_FIRC = 0u,
    SCU_ClkSrc_FXOSC= 2u,
    SCU_ClkSrc_SIRC = 3u,
} SCU_ClkSrc_Type;

/* SCU_STATUS_XXX_CLK_VALID flags. */
#define SCU_STATUS_FIRC_CLK_VALID    (1u << 0u)
#define SCU_STATUS_FXOSC_CLK_VALID   (1u << 1u)
#define SCU_STATUS_SXOSC_CLK_VALID   (1u << 2u)

/* system clock. */
void SCU_SetSysClkSrcMux(SCU_Type * base, SCU_ClkSrc_Type clk_src);
void SCU_SetSysClkSrcDiv(SCU_Type * base, uint32_t core_clk_div, uint32_t fast_bus_clk_div, uint32_t slow_bus_clk_div);
SCU_ClkSrc_Type SCU_GetSysClkSrcMux(SCU_Type * base);
bool SCU_GetSysClkSrcValidOn(SCU_Type *base, uint32_t clks); /* SCU_STATUS_XXX_CLK_VALID. */
void SCU_GetSysClkSrcDiv(SCU_Type * base, uint32_t *core_clk_div, uint32_t *fast_bus_clk_div, uint32_t *slow_bus_clk_div);

/* clock source. */

typedef struct
{
    bool EnableOnDeepsleepMode;
} SCU_FircConf_Type;

typedef struct
{
    bool EnableOnDeepsleepMode;
    bool EnableOnStandbyMode;
} SCU_SircConf_Type;

typedef struct
{
    bool EnableOnDeepsleepMode;
    bool EnableCrystalMode;
    uint32_t GainVal; /* 0-7, higher gain value results higher power and better performance, only in ctystal mode. */
} SCU_FxoscConf_Type;

typedef struct
{
    bool EnableOnDeepsleepMode;
    bool EnableOnStandbyMode;
    bool EnableCrystalMode;
    uint32_t GainVal; /* 0-1, higher gain value results higher power and better performance, only in ctystal mode. */
} SCU_SxoscConf_Type;

void SCU_SetFircConf(SCU_Type * base, SCU_FircConf_Type * conf); /* set conf null to disable. */
void SCU_SetSircConf(SCU_Type * base, SCU_SircConf_Type * conf); /* set conf null to disable. */
void SCU_SetFxoscConf(SCU_Type * base, SCU_FxoscConf_Type * conf); /* set conf null to disable. */
void SCU_SetSxoscConf(SCU_Type * base, SCU_SxoscConf_Type * conf); /* set conf null to disable. */

typedef enum
{
    SCU_ClkOutSrc_NONE = 0u,
    SCU_ClkOutSrc_FIRC = 1u,
    SCU_ClkOutSrc_SIRC = 2u,
    SCU_ClkOutSrc_FXOSC= 3u,
    SCU_ClkOutSrc_SXOSC= 4u,
    SCU_ClkOutSrc_LPO  = 5u,
    SCU_ClkOutSrc_CoreClk = 7u,
} SCU_ClkOutSrc_Type;

void SCU_SetClkOutSrcMux(SCU_Type *base, SCU_ClkOutSrc_Type clk_src, uint32_t clk_div); /* clk_div is 8-bit. */

/* cmu. */

typedef struct
{
    bool EnableResetOnCmuEvent;
    uint32_t CmuHighVal;
    uint32_t CmuLowVal;
} SCT_CmuConf_Type;

void SCU_SetCmuConf(SCU_Type * base, uint32_t cmu_idx, SCT_CmuConf_Type * conf);

#define SCU_CMU_STATUE_CLK_OUT_OF_RANGE (1u << 0u)
#define SCU_CMU_STATUE_LOSS_OF_REF_CLK  (1u << 1u)
#define SCU_CMU_STATUE_LOSS_OF_CLK      (1u << 1u)

uint32_t SCU_GetCmuStatusFlags(SCU_Type * base, uint32_t cmu_idx);

#endif /* __HAL_SCU_H__ */
